GitHub ActionsでDependabotの脆弱性修正PRのMerge処理を自動化する
こんにちは、CX事業本部 IoT事業部の若槻です。
前回のエントリでは、Dependabotにより脆弱性を修正するPull Requestが自動でOpenされる所まで確認してみました。
この脆弱性修正を、プロダクトへすぐに反映させるために自動化したい場合もあると思います。
今回は、GitHub ActionsでDependabotのOpenしたPull RequestのMerge処理を自動化してみました。
やってみた
こちらのドキュメントを参考にやってみます。
準備
対象のRepositoryの[Dependabot security updates]を有効化します。
Repositoryにdependabot config fileを作成します。Dependabot security updatesの作成するPull Requestに対する処理の自動化を行いたいので、open-pull-requests-limit
プロパティを0
とします。(もしくは不要であればconfig fileごと削除しても良いです。)
version: 2 updates: - package-ecosystem: "npm" directory: "/" schedule: interval: "daily" open-pull-requests-limit: 0
RepositoryをローカルにCloneし、必要に応じてnpm init
をしたら、あえてDependabot alertで検出される脆弱性を含むDependencyをインストールします。
$ npm install moment@2.24.0 $ npm ls --depth=0 test-220501@1.0.0 /Users/wakatsuki.ryuta/projects/cm-rwakatsuki/test-220501 └── moment@2.24.0
脆弱性がちゃんと含まれていますね。
$ npm audit # npm audit report moment <2.29.2 Severity: high
また、まだの場合は.gitignore
でnode_modules
を指定してCommit対象から除外します。
Workflow Configの作成
次のようなWorkflow Config fileを作成します。DependabotによりOpenされたPull Requestのメタデータ取得と、自動Mergeを行っています。
name: Dependabot auto-merge on: pull_request permissions: pull-requests: write contents: write jobs: dependabot: runs-on: ubuntu-latest if: ${{ github.actor == 'dependabot[bot]' }} steps: - name: Dependabot metadata id: metadata uses: dependabot/fetch-metadata@v1.1.1 with: github-token: "${{ secrets.GITHUB_TOKEN }}" - name: Enable auto-merge for Dependabot PRs if: ${{ steps.metadata.outputs.dependency-type == 'direct:production' }} run: gh pr merge --auto --merge "$PR_URL" env: PR_URL: ${{github.event.pull_request.html_url}} GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
- GitHub Actionsでは
secrets.GITHUB_TOKEN
に既定でReadonly権限のトークンが設定されますが、それをpermissions
で記載した内容で拡大しています。 if: ${{ github.actor == 'dependabot[bot]' }}
により、Pull RequestがDependabotにより自動Openされた時のみjobを実行するよにしています。- dependabot/fetch-metadata actionにより、WorkflowをトリガーしたPull Requestに関するDependabotのメタデータを取得できます。
- 取得したメタデータでは次の情報が含まれています。
- dependency-names:アップデートされるDependencyの名前。
- dependency-type:アップデートされるDependencyのタイプは
development
とproduction
のいずれかであるか。 - update-type:アップデートのされ方。セマンティックバージョニングの範囲内のアップデートであれば
version-update:semver-patch
という値が入る。
if: ${{ steps.metadata.outputs.dependency-type == 'direct:production' }}
のようにメタデータを使用した判定処理を入れることが可能です。ここではProductionのDependencyの場合にのみApproveをするようにしています。
動作確認
ここまでの変更をCommitしてリモートのデフォルトブランチにpushします。(実際にはfeatureにpush→デフォルトブランチにmergeという流れだと思いますが簡単のため省略)
するとDependabotによりalertが作成され、Pull RequestがOpenされました。
そしてそれをトリガーにしてWorkflowも実行され、正常に完了しました。
Pull Requestを見ると、Pull RequestがGitHub ActionsのBotによりMergeされています。
ハマった箇所
dependabot/fetch-metadataで必要な権限
最初次のようにWorkflow ConfigでPermissionをcontents: write
のみとして試しました。
name: Dependabot auto-merge on: pull_request permissions: contents: write jobs: dependabot: runs-on: ubuntu-latest if: ${{ github.actor == 'dependabot[bot]' }} steps: - name: Dependabot metadata id: metadata uses: dependabot/fetch-metadata@v1.1.1 with: github-token: "${{ secrets.GITHUB_TOKEN }}"
しかしdependabot/fetch-metadata
で403エラーとなりました。
そこでPermissionにpull-requests: write
を追加するとエラー無く動作するようになりました。メタデータを取得するだけなのでReadonlyのPermissionだけでも十分かと思いきやwrite権限も必要でした。
おわりに
GitHub ActionsでDependabotのOpenしたPull RequestのMerge処理を自動化してみました。
Dependencyのアップデートはプロダクトの動作に影響が出る可能性があるため本来なら検証環境での動作確認や対人レビューをきちんと経た上で行いたいところですが、ゼロデイ攻撃の恐れのある脆弱性が検知された場合はそんな悠長なことはして要られません。そのような場合に脆弱性への対処を最優先とするために、今回紹介した方法で脆弱性が検知されてから本番環境(あるいはステージング環境)へ反映されるまでのリードタイムを短縮することができます。Apache Log4jの件もあった昨今ですので一考に値するかと思います。
以上